package com.mingle.widget;

import com.mingle.widget.utils.ArgbEvaluator;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.app.Context;

/**
 * Created by zzz40500 on 15/4/4.
 */
public class ShapeLoadingView extends Component implements Component.DrawTask {

    /**
     * 用赛贝尔曲线画圆
     */
    private static final float mMagicNumber = 0.55228475f;
    private static final float genhao3 = 1.7320508075689f;
    private static final float mTriangle2Circle = 0.25555555f;
    private Shape mShape = Shape.SHAPE_CIRCLE;
    private ArgbEvaluator mArgbEvaluator = new ArgbEvaluator();
    private int mTriangleColor = 0xaa72d572;
    private int mCircleColor = 0xaa738ffe;
    private int mRectColor = 0xaae84e40;

    private Paint mPaint;
    private float mControlX = 0;
    private float mControlY = 0;
    private float mAnimPercent;

    /**
     * 是否loading中
     */
    public boolean mIsLoading = false;

    public ShapeLoadingView(Context context) {
        this(context, null);
    }

    public ShapeLoadingView(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }


    public ShapeLoadingView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setColor(new Color(mTriangleColor));
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILLANDSTROKE_STYLE);
        addDrawTask(this);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (getVisibility() == HIDE) {
            return;
        }
        // FIXME: 15/6/15  动画待优化
        switch (mShape) {
            case SHAPE_TRIANGLE:
                if (mIsLoading) {
                    mAnimPercent += 0.1611113;
                    int color = (int) mArgbEvaluator.evaluate(mAnimPercent, mTriangleColor, mCircleColor);
                    mPaint.setColor(new Color(color));
                    // triangle to circle
                    Path path = new Path();
                    path.moveTo(relativeXFromView(0.5f), relativeYFromView(0f));
                    if (mAnimPercent >= 1) {
                        mShape = Shape.SHAPE_CIRCLE;
                        mIsLoading = false;
                        mAnimPercent = 1;
                    }
                    float controlX = mControlX - relativeXFromView(mAnimPercent * mTriangle2Circle)
                            * genhao3;
                    float controlY = mControlY - relativeYFromView(mAnimPercent * mTriangle2Circle);
                    path.quadTo(relativeXFromView(1) - controlX, controlY, relativeXFromView(0.5f + genhao3 / 4), relativeYFromView(0.75f));
                    path.quadTo(relativeXFromView(0.5f), relativeYFromView(0.75f + 2 * mAnimPercent * mTriangle2Circle), relativeXFromView(0.5f - genhao3 / 4), relativeYFromView(0.75f));
                    path.quadTo(controlX, controlY, relativeXFromView(0.5f), relativeYFromView(0f));
                    path.close();
                    canvas.drawPath(path, mPaint);
                    getContext().getUITaskDispatcher().asyncDispatch(new Runnable() {
                        @Override
                        public void run() {
                            invalidate();
                        }
                    });
                } else {
                    Path path = new Path();
                    mPaint.setColor(new Color(mTriangleColor));
                    path.moveTo(relativeXFromView(0.5f), relativeYFromView(0f));
                    path.lineTo(relativeXFromView(1), relativeYFromView(genhao3 / 2f));
                    path.lineTo(relativeXFromView(0), relativeYFromView(genhao3 / 2f));
                    mControlX = relativeXFromView(0.5f - genhao3 / 8.0f);
                    mControlY = relativeYFromView(3 / 8.0f);
                    mAnimPercent = 0;
                    path.close();
                    canvas.drawPath(path, mPaint);
                }
                break;
            case SHAPE_CIRCLE:
                if (mIsLoading) {
                    float magicNumber = mMagicNumber + mAnimPercent;
                    mAnimPercent += 0.12;
                    if (magicNumber + mAnimPercent >= 1.9f) {
                        mShape = Shape.SHAPE_RECT;
                        mIsLoading = false;
                    }
                    int color = (int) mArgbEvaluator.evaluate(mAnimPercent, mCircleColor, mRectColor);
                    mPaint.setColor(new Color(color));
                    Path path = new Path();

                    path.moveTo(relativeXFromView(0.5f), relativeYFromView(0f));
                    path.cubicTo(
                            new Point(relativeXFromView(0.5f + magicNumber / 2), relativeYFromView(0f)),
                            new Point(relativeXFromView(1), relativeYFromView(0.5f - magicNumber / 2)),
                            new Point(relativeXFromView(1f), relativeYFromView(0.5f)));
                    path.cubicTo(
                            new Point(relativeXFromView(1), relativeXFromView(0.5f + magicNumber / 2)),
                            new Point(relativeXFromView(0.5f + magicNumber / 2), relativeYFromView(1f)),
                            new Point(relativeXFromView(0.5f), relativeYFromView(1f)));
                    path.cubicTo(
                            new Point(relativeXFromView(0.5f - magicNumber / 2), relativeXFromView(1f)),
                            new Point(relativeXFromView(0), relativeYFromView(0.5f + magicNumber / 2)),
                            new Point(relativeXFromView(0f), relativeYFromView(0.5f)));
                    path.cubicTo(
                            new Point(relativeXFromView(0f), relativeXFromView(0.5f - magicNumber / 2)),
                            new Point(relativeXFromView(0.5f - magicNumber / 2), relativeYFromView(0)),
                            new Point(relativeXFromView(0.5f), relativeYFromView(0f)));
                    path.close();
                    canvas.drawPath(path, mPaint);
                    getContext().getUITaskDispatcher().asyncDispatch(new Runnable() {
                        @Override
                        public void run() {
                            invalidate();
                        }
                    });
                } else {
                    mPaint.setColor(new Color(mCircleColor));
                    Path path = new Path();
                    float magicNumber = mMagicNumber;
                    path.moveTo(relativeXFromView(0.5f), relativeYFromView(0f));
                    path.cubicTo(
                            new Point(relativeXFromView(0.5f + magicNumber / 2), 0),
                            new Point(relativeXFromView(1), relativeYFromView(magicNumber / 2)),
                            new Point(relativeXFromView(1f), relativeYFromView(0.5f)));
                    path.cubicTo(
                            new Point(relativeXFromView(1), relativeXFromView(0.5f + magicNumber / 2)),
                            new Point(relativeXFromView(0.5f + magicNumber / 2), relativeYFromView(1f)),
                            new Point(relativeXFromView(0.5f), relativeYFromView(1f)));
                    path.cubicTo(
                            new Point(relativeXFromView(0.5f - magicNumber / 2), relativeXFromView(1f)),
                            new Point(relativeXFromView(0), relativeYFromView(0.5f + magicNumber / 2)),
                            new Point(relativeXFromView(0f), relativeYFromView(0.5f)));
                    path.cubicTo(
                            new Point(relativeXFromView(0f), relativeXFromView(0.5f - magicNumber / 2)),
                            new Point(relativeXFromView(0.5f - magicNumber / 2), relativeYFromView(0)),
                            new Point(relativeXFromView(0.5f), relativeYFromView(0f)));
                    mAnimPercent = 0;
                    path.close();
                    canvas.drawPath(path, mPaint);
                }
                break;
            case SHAPE_RECT:
                if (mIsLoading) {
                    mAnimPercent += 0.15;
                    if (mAnimPercent >= 1) {
                        mShape = Shape.SHAPE_TRIANGLE;
                        mIsLoading = false;
                        mAnimPercent = 1;
                    }
                    int color = (int) mArgbEvaluator.evaluate(mAnimPercent, mRectColor, mTriangleColor);
                    mPaint.setColor(new Color(color));
                    Path path = new Path();
                    path.moveTo(relativeXFromView(0.5f * mAnimPercent), 0);
                    path.lineTo(relativeYFromView(1 - 0.5f * mAnimPercent), 0);
                    float distanceX = (mControlX) * mAnimPercent;
                    float distanceY = (relativeYFromView(1f) - mControlY) * mAnimPercent;
                    path.lineTo(relativeXFromView(1f) - distanceX, relativeYFromView(1f) - distanceY);
                    path.lineTo(relativeXFromView(0f) + distanceX, relativeYFromView(1f) - distanceY);
                    path.close();
                    canvas.drawPath(path, mPaint);
                    getContext().getUITaskDispatcher().asyncDispatch(new Runnable() {
                        @Override
                        public void run() {
                            invalidate();
                        }
                    });
                } else {
                    mPaint.setColor(new Color(mRectColor));
                    mControlX = relativeXFromView(0.5f - genhao3 / 4);
                    mControlY = relativeYFromView(0.75f);
                    Path path = new Path();
                    path.moveTo(relativeXFromView(0f), relativeYFromView(0f));
                    path.lineTo(relativeXFromView(1f), relativeYFromView(0f));
                    path.lineTo(relativeXFromView(1f), relativeYFromView(1f));
                    path.lineTo(relativeXFromView(0f), relativeYFromView(1f));
                    path.close();
                    mAnimPercent = 0;
                    canvas.drawPath(path, mPaint);
                }
                break;
        }
    }

    private float relativeXFromView(float percent) {
        return getWidth() * percent;
    }

    private float relativeYFromView(float percent) {
        return getHeight() * percent;
    }

    /**
     * 改变下一个形状
     */
    public void changeShape() {
        mIsLoading = true;
        invalidate();
    }

    /**
     * 设置当前形状
     *
     * @param shape 形状对应的枚举
     */
    public void setShape(Shape shape) {
        mIsLoading = true;
        mShape = shape;
        invalidate();
    }

    /**
     * 形状的枚举类型，三角形、方形、圆形
     */
    public enum Shape {
        SHAPE_TRIANGLE, SHAPE_RECT, SHAPE_CIRCLE
    }

    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        if (visibility == VISIBLE) {
            invalidate();
        }
    }

    /**
     * 获取当前形状的对应枚举
     *
     * @return 当前形状的对应枚举
     */
    public Shape getShape() {
        return mShape;
    }

}
